package com.yuxl.admin.manager.auth.server.controller;

import com.yuxl.admin.common.core.utils.R;
import com.yuxl.admin.manager.auth.core.entity.*;
import com.yuxl.admin.manager.auth.core.repository.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;
@RequiredArgsConstructor
@RestController
@RequestMapping("/manager/role")
@Tag(name = "角色管理", description = "角色的 CRUD 操作")
public class AuthRoleController {

    private final AuthRoleRepository authRoleRepository;
    private final AuthUserRoleRepository authUserRoleRepository;
    private final AuthRolePowerRepository authRolePowerRepository;
    private final AuthInterfaceRepository authInterfaceRepository;
    private final AuthMenuRepository authMenuRepository;
    private final AuthOperateRepository authOperateRepository;
    private final AuthUserRepository authUserRepository;

    /**
     * 创建新角色
     * @param role 要创建的角色对象
     * @return 创建成功的角色对象
     */
    @PostMapping
    @Operation(summary = "创建新角色", description = "创建一个新的角色")
    public Mono<R<AuthRole>> create(@RequestBody AuthRole role) {
        // 保存新角色到数据库
        role.setCreateTime(LocalDateTime.now());
        return R.ok(authRoleRepository.save(role));
    }

    /**
     * 根据ID获取角色
     * @param id 角色ID
     * @return 角色对象
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取角色", description = "根据ID获取角色信息")
    public Mono<R<AuthRole>> getRoleById(@PathVariable Long id) {
        return R.ok(authRoleRepository.findById(id));
    }

    /**
     * 更新角色信息
     * @param id 要更新的角色ID
     * @param entity 包含更新信息的角色对象
     * @return 更新后的角色对象
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新角色", description = "更新指定ID的角色信息")
    public Mono<R<AuthRole>> updateRole(@PathVariable Long id, @RequestBody AuthRole entity) {
        return authRoleRepository.findById(id)
                // 根据ID查找现有角色
                .flatMap(existingRole -> {
                    entity.setId(id);
                    entity.setUpdateTime(LocalDateTime.now());
                    // 更新角色信息
                    return R.ok(authRoleRepository.save(entity));
                    // 保存更新后的角色
                })
                .switchIfEmpty(R.failed("更新角色失败"));
                // 如果找不到角色，抛出404错误
    }

    /**
     * 删除角色
     * @param id 要删除的角色ID
     * @return 无返回值
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除角色", description = "删除指定ID的角色")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public Mono<R<Void>> deleteRole(@PathVariable Long id) {
        return R.ok(authRoleRepository.deleteById(id));
        // 根据ID删除角色
    }

    /**
     * 获取所有角色
     * @return 所有角色的列表
     */
    @GetMapping
    @Operation(summary = "获取所有角色", description = "获取所有角色的列表")
    public Mono<R<List<AuthRole>>> getAllRoles() {
        return R.ok(authRoleRepository.findAll());
        // 获取所有角色
    }

    /**
     * 分页获取角色
     * @param page 页码
     * @param size 每页大小
     * @return 分页后的角色列表
     */
    @GetMapping("/page")
    @Operation(summary = "分页获取角色", description = "分页获取角色列表")
    public Mono<R<List<AuthRole>>> getRolesPage(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        return R.ok(authRoleRepository.findAll()
                // 获取所有角色
                .skip((long) page * size)
                // 跳过前面的角色
                .take(size));
                // 获取指定数量的角色

    }

    /**
     * 获取角色的用户
     * @param roleId 角色ID
     * @param roleMark 角色标记
     * @return 拥有指定角色的用户列表
     */
    @GetMapping("/users")
    @Operation(summary = "获取角色用户", description = "获取指定角色ID或角色标记的所有用户")
    public Mono<R<List<AuthUser>>> getUsersByRole(
            @RequestParam(required = false) Long roleId,
            @RequestParam(required = false) String roleMark) {
        if (roleId != null) {
            return R.ok(authUserRoleRepository.findByRoleId(roleId)
                    // 根据角色ID查找用户角色关系
                    .flatMap(userRole -> authUserRepository.findById(userRole.getUserId())));
                    // 根据用户ID查找用户
        } else if (roleMark != null) {
            return R.ok(authRoleRepository.findByMark(roleMark)
                    // 根据角色标记查找角色
                    .flatMap(role -> authUserRoleRepository.findByRoleId(role.getId()))
                    // 根据角色ID查找用户角色关系
                    .flatMap(userRole -> authUserRepository.findById(userRole.getUserId())));
                    // 根据用户ID查找用户
        } else {
            return R.ok();
            // 如果没有提供roleId或roleMark，返回空结果
        }
    }

    /**
     * 获取角色的接口
     * @param roleId 角色ID
     * @param roleMark 角色标记
     * @return 拥有指定角色的接口列表
     */
    @GetMapping("/interfaces")
    @Operation(summary = "获取角色接口", description = "获取指定角色ID或角色标记的所有接口")
    public Mono<R<List<AuthInterface>>> getInterfacesByRole(
            @RequestParam(required = false) Long roleId,
            @RequestParam(required = false) String roleMark) {
        if (roleId != null) {
            return R.ok(authRolePowerRepository.findByRoleId(roleId)
                    // 根据角色ID查找角色接口关系
                    .flatMap(roleInterface -> authInterfaceRepository.findById(roleInterface.getPowerId())));
            // 根据接口ID查找接口
        } else if (roleMark != null) {
            return R.ok(authRoleRepository.findByMark(roleMark)
                    // 根据角色标记查找角色
                    .flatMap(role -> authRolePowerRepository.findByRoleId(role.getId()))
                    // 根据角色ID查找用户角色关系
                    .flatMap(roleInterface -> authInterfaceRepository.findById(roleInterface.getPowerId())));
            // 根据用户ID查找用户
        } else {
            return R.ok();
            // 如果没有提供roleId或roleMark，返回空结果
        }
    }

    /**
     * 获取角色的菜单
     * @param roleId 角色ID
     * @param roleMark 角色标记
     * @return 拥有指定角色的菜单列表
     */
    @GetMapping("/menus")
    @Operation(summary = "获取角色菜单", description = "获取指定角色ID或角色标记的所有菜单")
    public Mono<R<List<AuthMenu>>> getMenusByRole(
            @RequestParam(required = false) Long roleId,
            @RequestParam(required = false) String roleMark) {
        if (roleId != null) {
            return R.ok(authRolePowerRepository.findByRoleId(roleId)
                    // 根据角色ID查找角色菜单关系
                    .flatMap(roleMenu -> authMenuRepository.findById(roleMenu.getPowerId())));
            // 根据菜单ID查找菜单
        } else if (roleMark != null) {
            return R.ok(authRoleRepository.findByMark(roleMark)
                    // 根据角色标记查找角色
                    .flatMap(role -> authRolePowerRepository.findByRoleId(role.getId()))
                    // 根据角色ID查找用户角色关系
                    .flatMap(roleMenu -> authMenuRepository.findById(roleMenu.getPowerId())));
            // 根据用户ID查找用户
        } else {
            return R.ok();
            // 如果没有提供roleId或roleMark，返回空结果
        }
    }

    /**
     * 获取角色的操作
     * @param roleId 角色ID
     * @param roleMark 角色标记
     * @return 拥有指定角色的操作列表
     */
    @GetMapping("/operates")
    @Operation(summary = "获取角色操作", description = "获取指定角色ID或角色标记的所有操作")
    public Mono<R<List<AuthOperate>>> getOperatesByRole(
            @RequestParam(required = false) Long roleId,
            @RequestParam(required = false) String roleMark) {
        if (roleId != null) {
            return R.ok(authRolePowerRepository.findByRoleId(roleId)
                    // 根据角色ID查找角色操作关系
                    .flatMap(roleOperate -> authOperateRepository.findById(roleOperate.getPowerId())));
            // 根据操作ID查找操作
        } else if (roleMark != null) {
            return R.ok(authRoleRepository.findByMark(roleMark)
                    // 根据角色标记查找角色
                    .flatMap(role -> authRolePowerRepository.findByRoleId(role.getId()))
                    // 根据角色ID查找用户角色关系
                    .flatMap(roleOperate -> authOperateRepository.findById(roleOperate.getPowerId())));
            // 根据用户ID查找用户
        } else {
            return R.ok();
            // 如果没有提供roleId或roleMark，返回空结果
        }
    }
}
